---
id: unit8
title: 第八章
---

## GET 和 POST 的请求的区别

Post 和 Get 是 HTTP 请求的两种方法，其区别如下：

- 「应用场景：」 (GET 请求是一个「幂等」的请求)一般 Get 请求用于对服务器资源不会产生影响的场景，比如说请求一个网页的资源。(而 Post 不是一个「幂等」的请求)一般用于对服务器资源会产生影响的情景，比如注册用户这一类的操作。（「幂等是指一个请求方法执行多次和仅执行一次的效果完全相同」）
- 「是否缓存：」 因为两者应用场景不同，浏览器一般会对 Get 请求缓存，但很少对 Post 请求缓存。
- 「传参方式不同：」 Get 通过查询字符串传参，Post 通过请求体传参。
- 「安全性：」 Get 请求可以将请求的参数放入 url 中向服务器发送，这样的做法相对于 Post 请求来说是不太安全的，因为请求的 url 会被保留在历史记录中。
- 「请求长度：」 浏览器由于对 url 长度的限制，所以会影响 get 请求发送数据时的长度。这个限制是浏览器规定的，并不是 RFC 规定的。
- 「参数类型：」 get 参数只允许 ASCII 字符，post 的参数传递支持更多的数据类型(如文件、图片)。

## POST 和 PUT 请求的区别

PUT 请求是向服务器端发送数据，从而修改数据的内容，但是不会增加数据的种类等，也就是说无论进行多少次 PUT 操作，其结果并没有不同。（可以理解为时「更新数据」）

POST 请求是向服务器端发送数据，该请求会改变数据的种类等资源，它会创建新的内容。（可以理解为是「创建数据」）

为什么 post 请求会发送两次请求? 1.第一次请求为 options 预检请求，状态码为:204

作用 1: 询问服务器是否支持修改的请求头，如果服务器支持，则在第二次中发送真正的请求
作用 2: 检测服务器是否为同源请求,是否支持跨域
作用：

2.第二次为真正的 post 请求

## 常见的 HTTP 请求头和响应头

HTTP Request Header  
Accept:浏览器能够处理的内容类型  
Accept-Charset:浏览器能够显示的字符集  
Accept-Encoding：浏览器能够处理的压缩编码  
Accept-Language：浏览器当前设置的语言  
Connection：浏览器与服务器之间连接的类型  
Cookie：当前页面设置的任何 Cookie  
Host：发出请求的页面所在的域  
Referer：发出请求的页面的 URL  
User-Agent：浏览器的用户代理字符串  
HTTP Responses Header  
Date：表示消息发送的时间，时间的描述格式由 rfc822 定义  
server:服务器名称  
Connection：浏览器与服务器之间连接的类型  
Cache-Control：控制 HTTP 缓存  
content-type:表示后面的文档属于什么 MIME 类型  
Content-Type
「常见的 Content-Type 属性值有以下四种：」

（1）application/x-www-form-urlencoded：浏览器的原生 form 表单，如果不设置 enctype 属性，那么最终就会以 application/x-www-form-urlencoded 方式提交数据。该种方式提交的数据放在 body 里面，数据按照 key1=val1&key2=val2 的方式进行编码，key 和 val 都进行了 URL 转码。

（2）multipart/form-data：该种方式也是一个常见的 POST 提交方式，通常表单上传文件时使用该种方式。

（3）application/json：服务器消息主体是序列化后的 JSON 字符串。

（4）text/xml：该种方式主要用来提交 XML 格式的数据。

## HTTP 状态码 304 是多好还是少好

「为什么会有 304」

服务器为了提高网站访问速度，对之前访问的部分页面指定缓存机制，当客户端在此对这些页面进行请求，服务器会根据缓存内容判断页面与之前是否相同，若相同便直接返回 304，此时客户端调用缓存内容，不必进行二次下载。

状态码 304 不应该认为是一种错误，而是对客户端「有缓存情况下」服务端的一种响应。

搜索引擎蜘蛛会更加青睐内容源更新频繁的网站。通过特定时间内对网站抓取返回的状态码来调节对该网站的抓取频次。若网站在一定时间内一直处于 304 的状态，那么蜘蛛可能会降低对网站的抓取次数。相反，若网站变化的频率非常之快，每次抓取都能获取新内容，那么日积月累，的回访率也会提高。

「产生较多 304 状态码的原因：」

页面更新周期长或不更新
纯静态页面或强制生成静态 html
「304 状态码出现过多会造成以下问题：」

网站快照停止；
收录减少；
权重下降。

## 常见的 HTTP 请求方法

GET: 向服务器获取数据；  
POST：发送数据给服务器，通常会造成服务器资源的新增修改；  
PUT：用于全量修改目标资源(看接口，也可以用于添加)；  
PATCH：用于对资源进行部分修改  
DELETE：用于删除指定的资源；  
HEAD：获取报文首部，与 GET 相比，不返回报文主体部分；使用场景是比如下载一个大文件前，先获取其大小再决定是否要下载，以此可以节约宽带资源  
OPTIONS：(浏览器自动执行)、询问支持的请求方法，用来跨域请求、预检请求、判断目标是否安全；  
CONNECT：要求在与代理服务器通信时建立「管道」，使用「管道」进行 TCP 通信；(把服务器作为跳板，让服务器代替用户去访问其他网页，之后把数据原原本本的返回给用户)  
TRACE: 该方法会让服务器原样返回任意客户端请求的信息内容，主要⽤于测试或诊断。

## 说说 Ajax 组成部分

Ajax(阿贾克斯)：全称 Asynchronous Javascript And XML(异步的 js 与 xml)

说人话：「用 js 发送异步的网络请求」

A : Asynchronous 异步  
J：Javascript  
A ：And  
X : XML 与 XMLHttpRequest

在 JSON 没有出来以前, 网络传输主要以 XML 格式数据为主。后来 JSON 问世，逐渐取代 XML。但是由于 ajax 技术出来的比 json 早，因此 xml 这个称呼一直保留至今
XML ：解决跨平台数据传输。

## 请介绍一下 XMLHTTPRequest 对象

「Ajax 的核心是 XMLHTTPRequest」。它是一种支持异步请求的技术。XMLHTTPRequest 使您可以使用 JavaScript 向服务器提出请求并处理响应，而不阻塞用户。可以在页面加载以后进行页面的局部更新

「使用方法」

「1.实例化 ajax 对象」

「2. open()」 ：创建 HTTP 请求 第一个参数是指定提交方式(post、get) 第二个参数是指定要提交的地址是哪 第三个参数是指定是异步还是同步(true 表示异步，false 表示同步) 第四和第五参数在 HTTP 认证的时候会用到。是可选的

「3.设置请求头」

「setRequestHeader」(Stringheader,Stringvalue) 「（使用 post 方式才会使用到，get 方法并不需要调用该方法）」

「4.发送请求」

「send(content)」 ：发送请求给服务器 如果是 get 方式，并不需要填写参数，或填写 null 如果是 post 方式，把要提交的参数写上去

「5. 注册回调函数」

```js
/* 1.ajax： 在页面不刷新的情况下向服务器请求数据
           2.XMLHttpRequest ：http请求对象，负责实现ajax技术（小黄人）
                （1）创建XMLHttpRequest对象
                        * 小黄人，相当于黄袍加身的跑腿外卖小哥哥
                （2）设置请求
                        * 告诉小黄人服务器地址
                （3）发送请求
                        * 小黄人出发去指定地址取外卖（数据）
                            * 2G网速：走路去的
                            * 3G网速：骑膜拜去的
                            * WIFI : 骑电动车去的
                            * 4G   ： 骑小牛牌电动车去的
                （4）注册回调函数
                        * 小黄人把取回的外卖送到你家门口
        
         */
//(1).实例化ajax对象
let xhr = new XMLHttpRequest();
//(2).设置请求方法和地址
xhr.open("post", "http://www.liulongbin.top:3009/api/login");
//(3).设置请求头（post请求才需要设置）
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//(4).发送请求 ： 参数格式  'key=value'
xhr.send("username=admin&password=123456");
//(5).注册回调函数
// xhr.onload = function() {};
xhr.onreadystatechange = function () {
  //onreadystatechange会触发多次，一般需要判断xhr.readState == 4 才获取响应数据
  if (xhr.readyState == 4) {
    console.log(xhr.responseText);
  }
};
```

7.2. onreadstatechange 事件

```js
*/ 1. onload事件 ：  接收服务器响应的数（一次请求，只会执行一次）
  */      2. onreadystatechang事件 : 作用与onload事件一致（一次请求，会执行多次）
  */          面试点：XMLHttpRequest对象的状态码 （xhr.readyState）
   */             0: 请求未建立  (创建了xhr对象，但是还没调用open)
   */             1: 服务器连接已建立
   */             2. 请求已接收  (send之后,服务器已经接收了请求)
   */             3. 请求处理中
   */             4. 请求已完成，且响应已就绪 （ 4状态码等同于onload事件 ）

      //(1).实例化ajax对象
      let xhr = new XMLHttpRequest()
      console.log(xhr.readyState) //0
      //(2).设置请求方法和地址
      xhr.open("post", "http://www.liulongbin.top:3009/api/login")
        console.log(xhr.readyState) //1
      //(3).设置请求头（post请求才需要设置）
      xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
      console.log(xhr.readyState) //1
      //(4).发送请求 ： 参数格式  'key=value'
      xhr.send("username=admin&password=123456")
        console.log(xhr.readyState) //1
      //(5).注册回调函数
      //a. onload 是新式浏览器才支持的
      //b. 如果要兼容更早的浏览器，可以使用 onreadystatechange
      //c. onreadystatechange触发时机 ：xhr.readState状态变化
      // xhr.onload = function() {};

      xhr.onreadystatechange = function() {
        console.log(xhr.readyState) //2,3,4
        //onreadystatechange会触发多次，一般需要判断xhr.readState == 4 才获取响应数据
        if (xhr.readyState == 4) {
          console.log(xhr.responseText)
        }
      }


```

7.3 如何上传文件（上传图片）

```js
/*文件上传思路总结 
      1. 给file表单注册onchange事件 
        * 当用户选择图片之后执行
      2. 获取用户选择的图片 
        * this.files[0]
      3. 创建FormData对象 
        * 只有FormData才可以上传文件
      4. 将图片添加到FormData对象中 
        * fd.append('参数名', this.files[0])
      5. 发送ajax请求
        * 文件上传请求方法一定是post, 且请求参数为 FormData对象
      */

//1. file类型表单自带一个选择文件点击按钮，当用户选择文件之后就会触发onchange事件
document.querySelector("#iptFile").onchange = function () {
  //this : file表单
  //(1)获取用户选择的文件
  let file = this.files[0];
  // 非空判断，如果内容为undefined，给出提示
  if (file == undefined) {
    return alert("请选择上传文件！");
  }
  //(2)创建FormData对象， 只有FormData对象才可以上传文件
  let fd = new FormData();
  //(3)添加文件
  fd.append("avatar", file);
  //(4)发送ajax请求, 参数为 FormData对象
  axios({
    method: "POST",
    url: "http://www.liulongbin.top:3009/api/upload/avatar",
    data: fd,
  }).then(({ data: res }) => {
    console.log(res);
    if (res.code != 200) {
      return alert(res.message);
    }
    // 成功后提示，修改图片路径
    alert("恭喜您，上传头像成功！");
    document.querySelector(
      "img"
    ).src = `http://www.liulongbin.top:3009${res.url}`;
  });
};
```

7.4 如何自定义上传文件按钮

```js
//自定义文件上传按钮思路
//(1)隐藏file表单
//(2)给自定义按钮添加一个点击事件
//(3)点击按钮的时候，触发 file表单的点击

document.querySelector("#btnChoose").onclick = function () {
  //dom对象.onclick()  :  只能触发你自己注册的onclick事件，没注册触发不了
  //dom对象.click() : 模拟鼠标点击。 触发注册的onclick事件 + 默认点击事件

  document.querySelector("#iptFile").click();
};
```

7.5 ajax 请求如何取消

```js
// 「1. 原生xhr取消请求」
var xhr = new XMLHttpRequest();
xhr.abort();
```

```js
//「2.axios取消请求」
```

```js
// 「1.使用 CancelToken.source 工厂方法创建 cancel token」

const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios
  .get("/user/123", {
    cancelToken: source.token,
  })
  .catch(function (thrown) {
    if (axios.isCancel(thrown)) {
      console.log("Request canceled", thrown.message);
    } else {
      // 处理错误
    }
  });

axios.post(
  "/user/123",
  {
    name: "小明",
  },
  {
    cancelToken: source.token,
  }
);

// 取消请求（message 参数是可选的）
source.cancel("canceled by the user.");
```

```js
// 「2.传递一个 executor 函数到 CancelToken 的构造函数来创建 cancel token」

const CancelToken = axios.CancelToken;
let cancel;

axios.get("/user/12345", {
  cancelToken: new CancelToken(function executor(c) {
    // executor 函数接收一个 cancel 函数作为参数
    cancel = c;
  }),
});

// cancel the request
cancel();
```

7.6 取消 ajax 请求有什么意义
已发出的请求可能仍然会到达后端  
取消后续的回调处理，避免多余的回调处理，以及特殊情况，先发出的后返回，导致回调中的数据错误覆盖  
取消 loading 效果，以及该请求的其他交互效果，特别是在单页应用中，A 页面跳转到 B 页面之后，A 页面的请求应该取消，否则回调中的一些处理可能影响 B 页面  
超时处理，错误处理等都省去了，节约资源

## 8. OPTIONS 请求方法及使用场景

OPTIONS 是除了 GET 和 POST 之外的其中一种 HTTP 请求方法。(浏览器自动执行)

OPTIONS 方法是用于请求获得由 Request-URI 标识的资源在请求/响应的通信过程中可以使用的功能选项。通过这个方法，客户端可以「在采取具体资源请求之前，决定对该资源采取何种必要措施，或者了解服务器的性能」。该请求方法的响应不能缓存。

OPTIONS 请求方法的「主要用途」有两个： - 获取服务器支持的所有 HTTP 请求方法； - 用来检查访问权限。例如：在进行 CORS 跨域资源共享时，对于复杂请求，就是使用 OPTIONS 方法发送「嗅探」请求，以判断是否有对指定资源的访问权限。

## 9. HTTP 1.0 和 HTTP 1.1 之间有哪些区别？

「连接方面」，http1.0 默认使用非持久连接，而 http1.1 默认使用持久连接。http1.1 通过使用持久连接来使多个 http 请求复用同一个 TCP 连接，以此来避免使用非持久连接时每次需要建立连接的时延。  
「资源请求方面」，在 http1.0 中，存在一些浪费带宽的现象，例如客户端只是需要某个对象的一部分，而服务器却将整个对象送过来了，并且不支持断点续传功能，http1.1 则在请求头引入了 range 头域，它允许只请求资源的某个部分，即返回码是 206（Partial Content），这样就方便了开发者自由的选择以便于充分利用带宽和连接。  
「缓存方面」，在 http1.0 中主要使用 header 里的 If-Modified-Since、Expires 来做为缓存判断的标准，http1.1 则引入了更多的缓存控制策略，例如 Etag、If-Unmodified-Since、If-Match、If-None-Match 等更多可供选择的缓存头来控制缓存策略。  
「http1.1」 中「新增了 host 字段」，用来指定服务器的域名。http1.0 中认为每台服务器都绑定一个唯一的 IP 地址，因此，请求消息中的 URL 并没有传递主机名（hostname）。但随着虚拟主机技术的发展，在一台物理服务器上可以存在多个虚拟主机，并且它们共享一个 IP 地址。因此有了 host 字段，这样就可以将请求发往到同一台服务器上的不同网站。  
http1.1 相对于 http1.0 还新增了很多「请求方法」，如 PUT、HEAD、OPTIONS 等。

## HTTP 1.1 和 HTTP 2.0 的区别

「二进制协议」：HTTP/2 是一个二进制协议。在 HTTP/1.1 版中，报文的头信息必须是文本（ASCII 编码），数据体可以是文本，也可以是二进制。HTTP/2 则是一个彻底的二进制协议，头信息和数据体都是二进制，并且统称为"帧"，可以分为头信息帧和数据帧。帧的概念是它实现多路复用的基础。  
「多路复用：」 HTTP/2 实现了多路复用，HTTP/2 仍然复用 TCP 连接，但是在一个连接里，客户端和服务器都可以同时发送多个请求或回应，而且不用按照顺序一一发送，这样就避免了"队头堵塞"【1】的问题。  
「数据流：」 HTTP/2 使用了数据流的概念，因为 HTTP/2 的数据包是不按顺序发送的，同一个连接里面连续的数据包，可能属于不同的请求。因此，必须要对数据包做标记，指出它属于哪个请求。HTTP/2 将每个请求或回应的所有数据包，称为一个数据流。每个数据流都有一个独一无二的编号。数据包发送时，都必须标记数据流 ID ，用来区分它属于哪个数据流。  
「头信息压缩：」 HTTP/2 实现了头信息压缩，由于 HTTP 1.1 协议不带状态，每次请求都必须附上所有信息。所以，请求的很多字段都是重复的，比如 Cookie 和 User Agent ，一模一样的内容，每次请求都必须附带，这会浪费很多带宽，也影响速度。HTTP/2 对这一点做了优化，引入了头信息压缩机制。一方面，头信息使用 gzip 或 compress 压缩后再发送；另一方面，客户端和服务器同时维护一张头信息表，所有字段都会存入这个表，生成一个索引号，以后就不发送同样字段了，只发送索引号，这样就能提高速度了。  
「服务器推送：」 HTTP/2 允许服务器未经请求，主动向客户端发送资源，这叫做服务器推送。使用服务器推送提前给客户端推送必要的资源，这样就可以相对减少一些延迟时间。这里需要注意的是 http2 下服务器主动推送的是静态资源，和 WebSocket 以及使用 SSE 等方式向客户端发送即时数据的推送是不同的。

## 「什么是队头堵塞」

队头阻塞是由 HTTP 基本的“请求 - 应答”模型所导致的。HTTP 规定报文必须是“一发一收”，这就形成了一个先进先出的“串行”队列。队列里的请求是没有优先级的，只有入队的先后顺序，排在最前面的请求会被最优先处理。如果队首的请求因为处理的太慢耽误了时间，那么队列里后面的所有请求也不得不跟着一起等待，结果就是其他的请求承担了不应有的时间成本，造成了队头堵塞的现象。

## 「队头阻塞的解决方案：」

并发连接：对于一个域名允许分配多个长连接，那么相当于增加了任务队列，不至于一个队伍的任务阻塞其它所有任务。（2）域名分片：将域名分出很多二级域名，它们都指向同样的一台服务器，能够并发的长连接数变多，解决了队头阻塞的问题。

## HTTP 和 HTTPS 协议的区别

HTTPS 协议需要 CA 证书，费用较高；而 HTTP 协议不需要；  
HTTP 协议是超文本传输协议，信息是明文传输的，HTTPS 则是具有安全性的 SSL 加密传输协议；  
使用不同的连接方式，端口也不同，HTTP 协议端口是 80，HTTPS 协议端口是 443；  
HTTP 协议连接很简单，是无状态的；HTTPS 协议是有 SSL 和 HTTP 协议构建的可进行加密传输、身份认证的网络协议，比 HTTP 更加安全。

## GET 方法 URL 长度限制的原因

实际上 HTTP 协议规范并没有对 get 方法请求的 url 长度进行限制，这个限制是特定的「浏览器」及「服务器」对它的限制。IE 对 URL 长度的限制是「2083」字节(2K+35)。由于 IE 浏览器对 URL 长度的允许值是「最小的」，所以开发过程中，只要 URL 不超过 2083 字节，那么在所有浏览器中工作都不会有问题。

```js
GET的长度值 = URL（2083）- （你的Domain+Path）-2（2是get请求中?=两个字符的长度）

```

下面看一下主流浏览器对 get 方法中 url 的长度限制范围：
Microsoft Internet Explorer (Browser)：IE 浏览器对 URL 的最大限制为「2083」个字符，如果超过这个数字，提交按钮没有任何反应。
Firefox (Browser)：对于 Firefox 浏览器 URL 的长度限制为 「65,536」 个字符。
Safari (Browser)：URL 最大长度限制为 「80,000」 个字符。
Opera (Browser)：URL 最大长度限制为 「190,000」 个字符。
Google (chrome)：URL 最大长度限制为 「8182」 个字符。

主流的服务器对 get 方法中 url 的长度限制范围：

    - Apache (Server)：能接受最大url长度为「8192」个字符。
    - Microsoft Internet Information Server(IIS)：能接受最大url的长度为「16384」个字符。

根据上面的数据，可以知道，get 方法中的 URL 长度最长不超过 2083 个字符，这样所有的浏览器和服务器都可能正常工作。

## 一个页面从输入 URL 到页面加载显示完成，这个过程中都发生了什么？

（1）「解析 URL：」 「首先会对 URL 进行解析，分析所需要使用的传输协议和请求的资源的路径」。如果输入的 URL 中的协议或者主机名不合法，将会把地址栏中输入的内容传递给搜索引擎。如果没有问题，浏览器会检查 URL 中是否出现了非法字符，如果存在非法字符，则对非法字符进行转义后再进行下一过程。

（2）「缓存判断：」 「浏览器会判断所请求的资源是否在缓存里」，如果请求的资源在缓存里并且没有失效，那么就直接使用，否则向服务器发起新的请求。

（3）「DNS 解析：」 下一步首先需要获取的是输入的 URL 中的域名的 IP 地址，首先会「判断本地是否有该域名的 IP 地址的缓存」，如果有则使用，「如果没有则向本地 DNS 服务器发起请求」。「本地 DNS 服务器也会先检查是否存在缓存」，如果「没有就会先向根域名服务器发起请求」，获得负责的顶级域名服务器的地址后，「再向顶级域名服务器请求」，然后获得负责的权威域名服务器的地址后，「再向权威域名服务器发起请求」，「最终获得域名的 IP 地址后，本地 DNS 服务器再将这个 IP 地址返回给请求的用户」。用户向本地 DNS 服务器发起请求属于递归请求，本地 DNS 服务器向各级域名服务器发起请求属于迭代请求。

（4）「获取 MAC 地址（选说）」 当浏览器得到 IP 地址后，「数据传输还需要知道目的主机 MAC 地址」，因为应用层下发数据给传输层，TCP 协议会指定源端口号和目的端口号，然后下发给网络层。网络层会将本机地址作为源地址，获取的 IP 地址作为目的地址。然后将下发给数据链路层，数据链路层的发送需要加入通信双方的 MAC 地址，本机的 MAC 地址作为源 MAC 地址，目的 MAC 地址需要分情况处理。通过将 IP 地址与本机的子网掩码相与，可以判断是否与请求主机在同一个子网里，如果在同一个子网里，可以使用 APR 协议获取到目的主机的 MAC 地址，如果不在一个子网里，那么请求应该转发给网关，由它代为转发，此时同样可以通过 ARP 协议来获取网关的 MAC 地址，此时目的主机的 MAC 地址应该为网关的地址。

（5）「TCP 三次握手：」 ，「确认客户端与服务器的接收与发送能力」，下面是 TCP 建立连接的三次握手的过程，首先客户端向服务器发送一个 SYN 连接请求报文段和一个随机序号，服务端接收到请求后向服务器端发送一个 SYN ACK 报文段，确认连接请求，并且也向客户端发送一个随机序号。客户端接收服务器的确认应答后，进入连接建立的状态，同时向服务器也发送一个 ACK 确认报文段，服务器端接收到确认后，也进入连接建立状态，此时双方的连接就建立起来了。

（6）「HTTPS 握手（选说）：」 「如果使用的是 HTTPS 协议，在通信前还存在 TLS 的一个四次握手的过程」。首先由客户端向服务器端发送使用的协议的版本号、一个随机数和可以使用的加密方法。服务器端收到后，确认加密的方法，也向客户端发送一个随机数和自己的数字证书。客户端收到后，首先检查数字证书是否有效，如果有效，则再生成一个随机数，并使用证书中的公钥对随机数加密，然后发送给服务器端，并且还会提供一个前面所有内容的 hash 值供服务器端检验。服务器端接收后，使用自己的私钥对数据解密，同时向客户端发送一个前面所有内容的 hash 值供客户端检验。这个时候双方都有了三个随机数，按照之前所约定的加密方法，使用这三个随机数生成一把秘钥，以后双方通信前，就使用这个秘钥对数据进行加密后再传输。

（7）「发送 HTTP 请求」

「服务器处理请求,返回 HTTP 报文」(响应)(文件)

（8）「页面渲染：」 浏览器首先会根据 html 文件(响应) 「建 DOM 树」，根据解析到的 css 文件构「建 CSSOM 树」，如果遇到 script 标签，则判端是否含有 defer 或者 async 属性，要不然 script 的加载和执行会造成页面的渲染的阻塞。「当 DOM 树和 CSSOM 树建立好后，根据它们来构建渲染树」。渲染树构建好后，会根据渲染树来进行布局。布局完成后，最后使用浏览器的 UI 接口对页面进行绘制。这个时候整个页面就显示出来了。

（9）「TCP 四次挥手：」 「最后一步是 TCP 断开连接的四次挥手过程」。若客户端认为数据发送完成，则它需要向服务端发送连接释放请求。服务端收到连接释放请求后，会告诉应用层要释放 TCP 链接。然后会发送 ACK 包，并进入 CLOSE_WAIT 状态，此时表明客户端到服务端的连接已经释放，不再接收客户端发的数据了。但是因为 TCP 连接是双向的，所以服务端仍旧可以发送数据给客户端。服务端如果此时还有没发完的数据会继续发送，完毕后会向客户端发送连接释放请求，然后服务端便进入 LAST-ACK 状态。客户端收到释放请求后，向服务端发送确认应答，此时客户端进入 TIME-WAIT 状态。该状态会持续 2MSL（最大段生存期，指报文段在网络中生存的时间，超时会被抛弃） 时间，若该时间段内没有服务端的重发请求的话，就进入 CLOSED 状态。当服务端收到确认应答后，也便进入 CLOSED 状态。

## 页面有多张图片，HTTP 是怎样的加载表现？

在 HTTP 1 下，浏览器对一个域名下最大 TCP 连接数为 6，所以会请求多次。可以用「多域名部署」解决。这样可以提高同时请求的数目，加快页面图片的获取速度。

在 HTTP 2 下，可以一瞬间加载出来很多资源，因为，HTTP2 支持多路复用，可以在一个 TCP 连接中发送多个 HTTP 请求。

## HTTP2 的头部压缩算法是怎样的？

HTTP2 的头部压缩是 HPACK 算法。在客户端和服务器两端建立“字典”，用索引号表示重复的字符串，采用哈夫曼编码来压缩整数和字符串，可以达到 50%~90%的高压缩率。

具体来说:

    - 在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键值对，对于相同的数据，不再通过每次请求和响应发送；
    - 首部表在HTTP/2的连接存续期内始终存在，由客户端和服务器共同渐进地更新；
    - 每个新的首部键值对要么被追加到当前表的末尾，要么替换表中之前的值。

## HTTP 请求报文的是什么样的？

请求报⽂有 4 部分组成:

- 请求⾏
- 请求头部
- 空⾏
- 请求体

「其中：」

（1）请求⾏包括：请求⽅法字段、URL 字段、HTTP 协议版本字段。它们⽤空格分隔。例如，GET /index.html HTTP/1.1。

（2）请求头部:请求头部由关键字/值对组成，每⾏⼀对，关键字和值⽤英⽂冒号“:”分隔

User-Agent：产⽣请求的浏览器类型。
Accept：客户端可识别的内容类型列表。
Host：请求的主机名，允许多个域名同处⼀个 IP 地址，即虚拟主机。
（3）请求体: post put 等请求携带的数据

## HTTP 响应报文的是什么样的？

请求报⽂有 4 部分组成:

响应⾏：由网络协议版本，状态码和状态码的原因短语组成，例如 HTTP/1.1 200 OK
响应头：响应部⾸组成
空⾏
响应体：服务器响应的数据

## HTTP 协议的优点和缺点

HTTP 是超文本传输协议，它定义了客户端和服务器之间交换报文的格式和方式，默认使用 80 端口。它使用 TCP 作为传输层协议，保证了数据传输的可靠性。

HTTP 协议具有以下「优点」：

支持客户端/服务器模式
「简单快速」：客户向服务器请求服务时，只需传送请求方法和路径。由于 HTTP 协议简单，使得 HTTP 服务器的程序规模小，因而通信速度很快。
「无连接」：无连接就是限制每次连接只处理一个请求。服务器处理完客户的请求，并收到客户的应答后，即断开连接，采用这种方式可以节省传输时间。
「无状态」：HTTP 协议是无状态协议，这里的状态是指通信过程的上下文信息。缺少状态意味着如果后续处理需要前面的信息，则它必须重传，这样可能会导致每次连接传送的数据量增大。另一方面，在服务器不需要先前信息时它的应答就比较快。
「灵活」：HTTP 允许传输任意类型的数据对象。正在传输的类型由 Content-Type 加以标记。
HTTP 协议具有以下「缺点」：

「无状态：」 HTTP 是一个无状态的协议，HTTP 服务器不会保存关于客户的任何信息。
「明文传输：」 协议中的报文使用的是文本形式，这就直接暴露给外界，不安全。
「不安全」
（1）通信使用明文（不加密），内容可能会被窃听；（2）不验证通信方的身份，因此有可能遭遇伪装；（3）无法证明报文的完整性，所以有可能已遭篡改；

## 说一下 HTTP 3.0

HTTP3.0，也称作 HTTP over QUIC。HTTP3.0 的核心是 QUIC(读音 quick)协议，由 Google 在 2015 年提出的 SPDY v3 演化而来的新协议，传统的 HTTP 协议是基于传输层 TCP 的协议，而 QUIC 是基于传输层 UDP 上的协议，可以定义成:HTTP3.0 基于 UDP 的安全可靠的 HTTP2.0 协议。

## HTTP 的两种连接模式

HTTP 协议是基于 TCP/IP，并且使用了「请求-应答」的通信模式。

「HTTP 协议有两种连接模式，一种是持续连接，一种非持续连接」。（1）非持续连接指的是服务器必须为每一个请求的对象建立和维护一个全新的连接。（2）持续连接下，TCP 连接默认不关闭，可以被多个请求复用。采用持续连接的好处是可以避免每次建立 TCP 连接三次握手时所花费的时间。

## 22. URL 有哪些组成部分

以下面的 URL 为例www.aspxfans.com:8080/news/index?ID=246188#name

从上面的 URL 可以看出，一个完整的 URL 包括以下几部分：

「协议部分」：该 URL 的协议部分为“http：”，这代表网页使用的是 HTTP 协议。在 Internet 中可以使用多种协议，如 HTTP，FTP 等等本例中使用的是 HTTP 协议。在"HTTP"后面的“//”为分隔符；  
「域名部分」：该 URL 的域名部分为www.aspxfans.com。一个URL中，也可以使用IP地址作为域名使用  
「端口部分」：跟在域名后面的是端口，域名和端口之间使用“:”作为分隔符。端口不是一个 URL 必须的部分，如果省略端口部分，将采用默认端口（HTTP 协议默认端口是 80，HTTPS 协议默认端口是 443）；  
「虚拟目录部分」：从域名后的第一个“/”开始到最后一个“/”为止，是虚拟目录部分。虚拟目录也不是一个 URL 必须的部分。本例中的虚拟目录是“/news/”；
「文件名部分」：从域名后的最后一个“/”开始到“？”为止，是文件名部分，如果没有“?”,则是从域名后的最后一个“/”开始到“#”为止，是文件部分，如果没有“？”和“#”，那么从域名后的最后一个“/”开始到结束，都是文件名部分。本例中的文件名是“index.asp”。文件名部分也不是一个 URL 必须的部分，如果省略该部分，则使用默认的文件名；  
「锚部分」：从“#”开始到最后，都是锚部分。本例中的锚部分是“name”。锚部分也不是一个 URL 必须的部分；  
「参数部分」：从“？”开始到“#”为止之间的部分为参数部分，又称搜索部分、查询部分。本例中的参数部分为“boardID=5&ID=24618&page=1”。参数可以允许有多个参数，参数与参数之间用“&”作为分隔符。

## 23.与缓存相关的 HTTP 请求头有哪些

强缓存：

    - Expires
    - Cache-Control

协商缓存：

    - Etag、If-None-Match
    - Last-Modified、If-Modified-Since

## 强缓存和协商缓存

「1.强缓存：」 不会向服务器发送请求，直接从缓存中读取资源，在 chrome 控制台的 Network 选项中可以看到该请求返回 200 的状态码，并且 size 显示 from disk cache 或 from memory cache 两种（灰色表示缓存）。

「2.协商缓存：」 向服务器发送请求，服务器会根据这个请求的 request header 的一些参数来判断是否命中协商缓存，如果命中，则返回 304 状态码并带上新的 response header 通知浏览器从缓存中读取资源；

共同点：都是从客户端缓存中读取资源；区别是强缓存不会发请求，协商缓存会发请求。

## 25. HTTP 的 keep-alive 有什么作用？

「http1.0 默认关闭，需要手动开启。http1.1 后默认开启」

「作用：」 使客户端到服务器端的链接持续有效(「长连接」)，当出现对服务器的后续请求时，keep-Alive 功能避免了建立或者重新建立链接。

「使用方法：」 在请求头中加上 Connection：keep-alive。

「优点：」

较少的 CPU 和内存的占用(因为要打开的连接数变少了，复用了连接)
减少了后续请求的延迟(无需再进行握手)
「缺点：」 本来可以释放的资源仍旧被占用。有的请求已经结束了，但是还一直连接着。

「解决方法：」 服务器设置过期时间和请求次数，超过这个时间或者次数就断掉连接。

## OSI 的七层模型是什么？

ISO 于 1978 年开发的一套标准架构 ISO 模型，被引用来说明数据通信协议的结构和功能。

OSI 在功能上可以划分为两组：

网络群组：物理层、数据链路层、网络层

使用者群组：传输层、会话层、表示层、应用层

| OSI 七层网络模型 | TCP/IP 四层概念模型 | 对应网络协议                                                                                                                                        |
| :--------------: | :-----------------: | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|    7：应用层     |       应用层        | HTTP、RTSP TFTP（简单文本传输协议）、FTP、 NFS（数域筛法，数据加密）、WAIS`（广域信息查询系统）                                                     |
|    6：表示层     |       应用层        | Telnet（internet 远程登陆服务的标准协议）、Rlogin、SNMP（网络管理协议）、Gopher                                                                     |
|    5：会话层     |       应用层        | SMTP（简单邮件传输协议）、DNS（域名系统）                                                                                                           |
|    4：传输层     |       传输层        | TCP（传输控制协议）、UDP（用户数据报协议））                                                                                                        |
|    3：网络层     |       网际层        | ARP（地域解析协议）、RARP、AKP、UUCP（Unix to Unix copy）                                                                                           |
|  2：数据链路层   |     数据链路层      | FDDI（光纤分布式数据接口）、Ethernet、Arpanet、PDN（公用数据网）、SLIP（串行线路网际协议）PPP（点对点协议，通过拨号或专线方建立点对点连接发送数据） |
|    1：物理层     |       物理层        | SMTP（简单邮件传输协议）、DNS（域名系统）                                                                                                           |


其中高层（7、6、5、4层）定义了应用程序的功能，下面三层（3、2、1层）主要面向通过网络的端到端的数据流







